package org.test.algorithm;


import java.util.Random;

/**
 * 模拟退火算法（Simulated Annealing, SA）
 */
public class SimulatedAnnealing {

    /**
     * 定义一个简单的二维函数，例如 f(x, y) = x^2 + y^2
     *
     * @param x
     * @param y
     * @return
     */
    public static double objectiveFunction(double x, double y) {
        return x * x + y * y;
    }

    /**
     * 生成一个新解
     *
     * @param currentSolution 初始解
     * @param stepSize        初始温度
     * @return
     */
    public static double[] generateNeighbor(double[] currentSolution, double stepSize) {
        Random rand = new Random();
        double[] newSolution = new double[currentSolution.length];
        for (int i = 0; i < currentSolution.length; i++) {
            newSolution[i] = currentSolution[i] + (rand.nextDouble() * 2 - 1) * stepSize;
        }
        return newSolution;
    }

    /**
     * 模拟退火算法主函数
     *
     * @param initialSolution 初始解
     * @param initialTemp     初始温度
     * @param coolingRate     冷却速率
     * @param maxIterations   最大迭代次数
     * @return
     */
    public static double[] simulatedAnnealing(double[] initialSolution, double initialTemp, double coolingRate, int maxIterations) {
        double[] currentSolution = initialSolution;
        double temperature = initialTemp;
        Random rand = new Random();

        for (int iteration = 0; iteration < maxIterations; iteration++) {
            // 生成新解
            double[] neighborSolution = generateNeighbor(currentSolution, temperature);

            // 计算新解和当前解的目标函数值
            double currentObjective = objectiveFunction(currentSolution[0], currentSolution[1]);
            double neighborObjective = objectiveFunction(neighborSolution[0], neighborSolution[1]);

            // 接受新解的概率
            if (neighborObjective < currentObjective) {
                // 如果新解更优，则接受
                currentSolution = neighborSolution;
            } else {
                // 如果新解较差，则以一定概率接受
                double acceptanceProbability = Math.exp((currentObjective - neighborObjective) / temperature);
                if (rand.nextDouble() < acceptanceProbability) {
                    currentSolution = neighborSolution;
                }
            }

            // 降低温度
            temperature *= coolingRate;

            // 打印当前迭代信息（可选）
            System.out.println("次数: " + iteration + ", 温度: " + temperature + ", 方案: (" + currentSolution[0] + ", " + currentSolution[1] + "), Objective: " + currentObjective);
        }

        return currentSolution;
    }

    public static void main(String[] args) {
        // 初始解
        double[] initialSolution = {5.0, 5.0};
        // 初始温度
        double initialTemp = 100.0;
        // 冷却速率
        double coolingRate = 0.99;
        // 最大迭代次数
        int maxIterations = 1000;

        // 运行模拟退火算法
        double[] optimalSolution = simulatedAnnealing(initialSolution, initialTemp, coolingRate, maxIterations);

        // 输出最优解
        System.out.println("Optimal Solution: (" + optimalSolution[0] + ", " + optimalSolution[1] + ")");
    }
}